package sdk.webview.fmc.com.fmcsdk.db;

import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 单条表格数据类，包括相关联的子表数据
 * @author Evan
 *
 */
public class Record implements Parcelable {

	/**
	 * 记录是否需要同步的标记
	 */
	public enum Sync {
		
		/**
		 * 不需要同步，需要同步，已同步,同步失败四种状态
		 */
		UNSYNC,SYNC,SYNCED,SYNCERROR;
	}
	
	//主表名称
	private String table;
	//同步状态,默认为不同步状态
	private Sync syncState = Sync.UNSYNC;
	
	//该条数据是否被修改
	private boolean changed = false;
	
	//主表数据
	private Map<String, String> fieldValue;
	//子表数据
	private Map<String, List<Record>> childrens;
	
	public Record(String table){
		this.table = table;
		childrens = new HashMap<String, List<Record>>();
		fieldValue = new HashMap<String, String>();
	}
	
	public String getTable() {
		return table;
	}

	public void setTable(String table) {
		this.table = table;
	}

	public Sync getSyncState() {
		return syncState;
	}
	
	public void setSyncState(Sync syncState) {
		this.syncState = syncState;
		fieldValue.put(Table.SYNC, syncState.name());
	}

	public void setSyncStateWithChange(Sync syncState) {
		setChanged(true);
		setSyncState(syncState);
	}

	/**
	 * 添加数据
	 * @param field
	 * @param value
	 */
	public void setValue(String field, String value){
		//设置值表示被修改过
		setChanged(true);
		//修改过设置状态为需要同步
		setSyncStateWithChange(Sync.SYNC);
		fieldValue.put(field, value);
	}
	
	/**
	 * 添加数据
	 * @param field
	 * @param date
	 */
	public void setValue(String field, Date date){
		setValue(field, date.getTime());
	}
	
	public void setValue(String field, long value){
		setValue(field, String.valueOf(value));
	}
	
	public void setValue(String field, double value){
		setValue(field, String.valueOf(value));
	}
	
	public void setValue(String field, int value){
		setValue(field, String.valueOf(value));
	}
	
	/**
	 * 添加数据
	 * @param field
	 * @param bool
	 */
	public void setValue(String field, boolean bool){
		if(bool)
			setValue(field, 1);
		else
			setValue(field, 0);
	}
	
	/**
	 * 添加多条数据
	 * @param map
	 */
	public void setValue(Map<String, String> map){
		fieldValue.putAll(map);
	}
	
	
	/**
	 * 获取对应属性值
	 * @param field
	 * @return value,如果没有返回null
	 */
	public String getString(String field){
//		return fieldValue.get(field);
		return getString(field, "");
	}
	
	/**
	 * 获取对应属性值
	 * @param field 字段
	 * @param defaultValue 默认返回值
	 * @return
	 */
	public String getString(String field, String defaultValue){
		String value = fieldValue.get(field);
		if(value == null){
			return defaultValue;
		}
		return value;
	}
	
	/**
	 * 获取对应属性值
	 * @param field
	 * @return value,如果没有返回null
	 */
	public Date getDate(String field){
		Date date = null;
		String value = fieldValue.get(field);
		if(value==null || value.isEmpty()){
			return null;
		}else{
			try {
				long milliseconds = Long.valueOf(value);
				date = new Date(milliseconds);
			} catch (NumberFormatException e) {
				return null;
			}
		}
		return date;
	}
	
	/**
	 * 获取对应属性值
	 * @param field
	 * @return value,如果没有返回false
	 */
	public boolean getBoolean(String field){
		String value = fieldValue.get(field);
		if("1".equals(value))
			return true;
		else
			return false;
	}
	
	public int getInt(String field){
		String value = fieldValue.get(field);
		if(value!=null && !value.isEmpty()){
			return Integer.parseInt(value);
		}else{
			return -1;
		}
	}
	
	public long getLong(String field){
		String value = fieldValue.get(field);
		if(value!=null && !value.isEmpty()){
			return Long.parseLong(value);
		}else{
			return 0;
		}
	}
	
	public double getDouble(String field){
		String value = fieldValue.get(field);
		if(value!=null && !value.isEmpty()){
			if (value.contains(",")){
				value.replace(",","");
			}
			return Double.parseDouble(value.trim());
		}
		else{
			return 0.0;
		}
	}
	
	public boolean isNull(String field){
		String value = fieldValue.get(field);
		return TextUtils.isEmpty(value);
	}
	
	/**
	 * 获取主数据的键值
	 * @return
	 */
	public Set<String> getFields(){
		return fieldValue.keySet();
	}
	
	/**
	 * 获取子表的关系名(即表名)
	 * @return
	 */
	public Set<String> getChildrenName(){
		return childrens.keySet();
	}
	
	/**
	 * 是否有子级
	 * @return
	 */
	public boolean hasChildren(){
		if(null == childrens || childrens.size() == 0)
			return false;
		else
			return true;
	}
	/**
	 * 获取指定子级的所有内容
	 * @param childrenName
	 * @return
	 */
	public List<Record> getChildren(String childrenName){
		List<Record> childlist = childrens.get(childrenName);
		if(childlist == null){
			childlist =  new ArrayList<Record>();
		}
		return childlist;
	}
	
	/**
	 * 添加子类内容
	 * @param childreName
	 * @param pao
	 */
	public void addChild(String childreName, Record pao){
		if(childrens.containsKey(childreName)){
			childrens.get(childreName).add(pao);
		}else{
			List<Record> listPao = new ArrayList<Record>();
			listPao.add(pao);
			childrens.put(childreName, listPao);
		}
	}
	
	/**
	 * 添加子级的多条内容
	 * @param childrenName
	 * @param listPao
	 */
	public void addChild(String childrenName, List<Record> listPao){
		if(childrens.containsKey(childrenName)){
			childrens.get(childrenName).addAll(listPao);
		}else{
			childrens.put(childrenName, listPao);
		}
	}
	
	/**
	 * 移除指定子级的内容
	 * @param childrenName
	 */
	public void removeChildren(String childrenName){
		childrens.remove(childrenName);
	}
	
	/**
	 * 移除所有子级内容
	 */
	public void clearAllChildrens(){
		childrens.clear();
	}

	public boolean isChanged() {
		return changed;
	}

	public void setChanged(boolean changed) {
		this.changed = changed;
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeString(table);
		dest.writeSerializable(syncState);
		dest.writeBooleanArray(new boolean[]{changed});
		dest.writeMap(fieldValue);
		dest.writeMap(childrens);
//		Bundle val = new Bundle();
//		Iterator<String> iter = childrens.keySet().iterator();
//		while (iter.hasNext()) {
//			String key = iter.next();
//			ArrayList<Record> value = (ArrayList<Record>)childrens.get(key);
//			val.putParcelableArrayList(key, value);
//		}
//		dest.writeBundle(val);
	}
	
	public static final Creator<Record> CREATOR = new Creator<Record>() {

		@Override
		public Record createFromParcel(Parcel source) {
			
			Record record = new Record(source.readString());
			record.syncState = (Sync)source.readSerializable();
			
			boolean[] bool = new boolean[1];
			source.readBooleanArray(bool);
			record.changed = bool[0];
			
//			record.fieldValue = source.readHashMap(HashMap.class.getClassLoader());
			source.readMap(record.fieldValue, HashMap.class.getClassLoader());
			source.readMap(record.childrens, Record.class.getClassLoader());
//			HashMap.class.getClassLoader();
//			Bundle bundle = source.readBundle(Record.class.getClassLoader());
//			Iterator<String> iter = bundle.keySet().iterator();
//			while (iter.hasNext()) {
//				String key = (String) iter.next();
//				List<Record> list = bundle.getParcelableArrayList(key);
//				record.childrens.put(key, list);
//			}
			
			return record;
		}

		@Override
		public Record[] newArray(int size) {
			return new Record[size];
		}
	}; 
	//复制一个相同值的record
	public Record copy(){
		Record record=new Record(this.table);
		Set<String> keySet=this.getFields();
		for(String key:keySet){
			record.setValue(key, fieldValue.get(key));
		}
		if(this.hasChildren()){
			Set<String> keyChildSet=this.getChildrenName();
			for(String keyChild:keyChildSet){
				record.addChild(keyChild, this.getChildren(keyChild));
			}
		}
		return record;
	}
	
	@Override
	public String toString() {
		Set<String> keySet=this.getFields();
		String recordString="{";
		for(String key:keySet){
			recordString=recordString+"\""+key+"\""+":\""+fieldValue.get(key)+"\",";
		}
		if(this.hasChildren()){
			recordString=recordString+"{";
			Set<String> keyChildSet=this.getChildrenName();
			for(String keyChild:keyChildSet){
				recordString=recordString+"\""+keyChild+"\":\""+fieldValue.get(keyChild)+"\",";
			}
			recordString=recordString+"}";
		}
		recordString=recordString+"}";
		return recordString;
	}
	
	public void remove(Object object){
		fieldValue.remove(object);
	}
	
	public boolean containsKey(Object object){
		return fieldValue.containsKey(object);
	}
}
